package com.qing.config.security.utils;

import com.alibaba.fastjson.JSONArray;
import com.baidu.aip.face.AipFace;
import com.baidu.aip.face.MatchRequest;
import com.baidu.aip.util.Base64Util;
import org.json.JSONObject;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * 人脸识别工具
 *
 * @author qinghua
 * @date 2022/6/1 11:04
 */
@Component
public class FaceUtil {

    // 活体检测控制
    private static final String LIVENESS_CONTROL = "LOW";
    // 返回检测结果数量
    private static final String MAX_USER_NUM = "1";
    // 人脸注册时id重复的策略
    private static final String ACTION_TYPE = "REPLACE";

    private static final String IMAGE_TYPE = "BASE64";

    private static final String MATCH_THRESHOLD = "70";

    /**
     * 设置APPID、AK、SK
     */
    private static final String APP_ID = "26356501";
    private static final String API_KEY = "Gp6A5FrhVA8a5eBPuuPl37Cd";
    private static final String SECRET_KEY = "yTNnOSa6WRHXe1RlpTgyNo4DvZRqjRW3";

    private static AipFace client = new AipFace(APP_ID, API_KEY, SECRET_KEY);

    /**
     * 创建单例避免多次获取sdk
     */
    public static AipFace getClient() {
        client.setConnectionTimeoutInMillis(2000);
        client.setSocketTimeoutInMillis(60000);
        return client;
    }

    /**
     * 比较图片地址
     *
     * @param filePath1
     * @param filePath2
     * @return {@link JSONObject }
     */
    public String compareFaceLocal1(String filePath1, String filePath2) {
        // 读本地图片
        byte[] bytes1 = FileUtils.fileToBytes(filePath1);
        byte[] bytes2 = FileUtils.fileToBytes(filePath2);

        String image1 = encodeBase64(bytes1);
        String image2 = encodeBase64(bytes2);

        // 人脸对比
        // image1/image2也可以为url或facetoken, 相应的imageType参数需要与之对应。
        MatchRequest req1 = new MatchRequest(image1, IMAGE_TYPE);
        MatchRequest req2 = new MatchRequest(image2, IMAGE_TYPE);
        ArrayList<MatchRequest> requests = new ArrayList<>();
        requests.add(req1);
        requests.add(req2);

        return getClient().match(requests).toString();
    }

    /**
     * 比较base64
     *
     * @param base641
     * @param base642
     * @return {@link JSONObject }
     */
    public String compareFaceLocal(String base641, String base642) {
        // 人脸对比
        // image1/image2也可以为url或facetoken, 相应的imageType参数需要与之对应。
        MatchRequest req1 = new MatchRequest(base641, IMAGE_TYPE);
        MatchRequest req2 = new MatchRequest(base642, IMAGE_TYPE);
        ArrayList<MatchRequest> requests = new ArrayList<>();
        requests.add(req1);
        requests.add(req2);

        return getClient().match(requests).toString();
    }

    /**
     * 人脸比对
     * @param base64  图片
     * @param groupIdList  组列表（以逗号隔开）
     * @return {@link String }
     * {"result":{"face_token":"68b08bb3c5fe1f9aad8ffcefa8cb0b9c","user_list":[{"score":100,"group_id":"test01","user_id":"111","user_info":""}]},
     * "log_id":1438371074,"error_msg":"SUCCESS","cached":0,"error_code":0,"timestamp":1654075438}
     */
    public String searchFace(String base64, String groupIdList) {
        // 传入可选参数调用接口
        HashMap<String, Object> options = new HashMap<>();
        options.put("match_threshold", MATCH_THRESHOLD);
        options.put("quality_control", "NORMAL");
        options.put("liveness_control", LIVENESS_CONTROL);
        options.put("max_user_num", MAX_USER_NUM);

        // 人脸搜索
        return getClient().search(base64, IMAGE_TYPE, groupIdList, options).toString();
    }

    /**
     * 添加人脸信息
     * @param base64  图片
     * @param groupId  组
     * @param userId  用户
     * @return {@link String }
     * {"result":{"face_token":"68b08bb3c5fe1f9aad8ffcefa8cb0b9c",
     * "location":{"top":58.8,"left":71.67,"rotation":10,"width":79,"height":63}},
     * "log_id":2031420824,"error_msg":"SUCCESS","cached":0,"error_code":0,"timestamp":1654076031}
     */
    public String addFace(String base64, String groupId, String userId) {
        // 传入可选参数调用接口
        HashMap<String, String> options = new HashMap<>();
        options.put("match_threshold", MATCH_THRESHOLD);
        options.put("quality_control", "NORMAL");
        options.put("liveness_control", LIVENESS_CONTROL);

        return getClient().addUser(base64, IMAGE_TYPE, groupId, userId, options).toString();
    }

    /**
     *
     * @param base64  图片
     * @param groupId  组
     * @param userId  用户
     * @return {@link String }
     */
    public String updateFace(String base64, String groupId, String userId) {
        // 传入可选参数调用接口
        HashMap<String, String> options = new HashMap<>();
        options.put("match_threshold", MATCH_THRESHOLD);
        options.put("user_info", "user's info");
        options.put("quality_control", "NORMAL");
        options.put("liveness_control", LIVENESS_CONTROL);
        options.put("action_type", ACTION_TYPE);

        return getClient().updateUser(base64, IMAGE_TYPE, groupId, userId, options).toString();
    }

    /**
     * 删除用户人脸照片
     * @param groupId  组
     * @param userId  用户
     * @return {@link String } {"result":null,"log_id":1889349422,"error_msg":"SUCCESS","cached":0,"error_code":0,"timestamp":1654075889}
     */
    public String deleteFace(String groupId, String userId){
        // 传入可选参数调用接口
        HashMap<String, String> options = new HashMap<>();

        // 人脸删除
        JSONObject res = getClient().deleteUser(groupId, userId, options);
        return res.toString();
    }

    /**
     * 解析返回结果json
     * {"result":{"face_token":"68b08bb3c5fe1f9aad8ffcefa8cb0b9c","user_list":[{"score":100,"group_id":"test01","user_id":"111","user_info":""}]},
     * "log_id":1438371074,"error_msg":"SUCCESS","cached":0,"error_code":0,"timestamp":1654075438}
     *
     * @param str 人脸比对结果
     * @return {@link com.alibaba.fastjson.JSONObject }
     */
    public com.alibaba.fastjson.JSONObject getSearchResult(String str){
       return com.alibaba.fastjson.JSONObject.parseObject(
               JSONArray.parseArray(
                       com.alibaba.fastjson.JSONObject.parseObject(
                               com.alibaba.fastjson.JSONObject.parseObject(str).getString("result")
                       ).getString("user_list")
               ).get(0).toString()
       );
    }

    /**
     * 编码
     *
     * @param form
     */
    public static String encodeBase64(byte[] form) {
        return Base64Util.encode(form);
    }

    /**
     * 解码
     *
     * @param data
     */
    public static byte[] decodeBase64(String data) {
        return Base64Util.decode(data);
    }
}

